package fr.umlv.escapeir.weapon;

import java.awt.Image;
import java.util.ArrayList;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.common.MathUtils;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;

import fr.umlv.escapeir.GameWorld;
import fr.umlv.escapeir.behavior.Behavior;
import fr.umlv.escapeir.behavior.Behaviors;
import fr.umlv.escapeir.behavior.LinearMove;
import fr.umlv.escapeir.game.WorldActor;
import fr.umlv.escapeir.painter.AnimatedWorldPainter;
import fr.umlv.escapeir.painter.ImageManager;
import fr.umlv.escapeir.painter.WorldGraphics2D;

class Shiboleet implements Weapon {
	
	private static final int LOADING_TIME = 2;
	private static final int BALL_SIZE = 5;
	private static final int BALL_NUMBER = 8;
	private static final int SPEED = 50;
	
	private final GameWorld world;
	private final WorldActor actor;
	private final Image image;
	private final int groupIndex;
	private final float maxSize;
	private final ArrayList<Body> bodies;
	
	private AnimatedWorldPainter painter;
	private Behavior behavior;
	
	private float size;

	Shiboleet (WorldActor actor, int groupIndex) {
		this.image = ImageManager.self().load("shiboleet.png");
		this.actor = actor;
		this.maxSize = image.getHeight(null)/2;
		this.world = actor.getWorld();
		this.groupIndex = groupIndex;
		this.painter = new AnimatedWorldPainter() {
			
			private final float padding = maxSize/(LOADING_TIME*GameWorld.STEP_PER_SECOND);

			@Override
			public void apply() {
				if (size > maxSize) return;
				size += padding;
			}
			@Override
			public void render(WorldGraphics2D painter) {
				painter.save();
				painter.translateFromWorld(getPosition());
				painter.rotate(getAngle());
				painter.drawRectWithImage(new Vec2(-size, size), new Vec2(size, -size), image);
				painter.restore();
			}
		};

		behavior = Behaviors.INERTIA;
		bodies = new ArrayList<>();
	}

	@Override
	public Type getType() {
		return WorldActor.Type.WEAPON;
	}

	@Override
	public Vec2 getPosition() { 
		Vec2 pos = new Vec2(actor.getPosition());
		return pos;
	}

	@Override
	public float getAngle() {
		return 0;
	}

	@Override
	public GameWorld getWorld() {
		return world;
	}

	@Override
	public void render(WorldGraphics2D painter) {
		this.painter.render(painter);
	}

	@Override
	public void apply() {
		painter.apply();
		behavior.apply();
	}

	@Override
	public void touch(WorldActor actor) {}

	@Override
	public boolean fire(float theta) {
		if (size < maxSize) return false;

		BodyDef bdef = new BodyDef();
		bdef.type = BodyType.DYNAMIC;
		bdef.userData = this;
		bdef.position.set(getPosition());

		final CircleShape shape = new CircleShape();
		shape.m_radius = BALL_SIZE;

		FixtureDef fdef = new FixtureDef();
		fdef.restitution = 0;
		fdef.density = 0;
		fdef.shape = shape;
		fdef.isSensor = true;
		fdef.filter.groupIndex = groupIndex;
		
		float step = (2*MathUtils.PI)/BALL_NUMBER;
		for (int i=0; i<BALL_NUMBER; ++i) {
			float angle = i*step;
			Body b = world.createBody(bdef);
			b.createFixture(fdef);
			Behavior behavior = new LinearMove(b, angle, SPEED);
			behavior.apply();
			bodies.add(b);
		}
		
		world.addActor(this);
		
		painter = new AnimatedWorldPainter() {
			
			@Override
			public void apply() {}
			
			@Override
			public void render(WorldGraphics2D painter) {
				for (Body b : bodies) {
					painter.save();
					//System.out.println(b.getPosition());
					painter.translateFromWorld(b.getPosition());
					painter.drawCircleWithImage(shape, image);
					painter.restore();
				}
			}
		};

		return true;
	}

}
